﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web.Mvc;
using BLL.Services;
using BLL.Services.Users;
using BLL.Services.Users.Listing;
using MvcContrib.Sorting;
using MvcContrib.UI.Grid;
using Web.Areas.Admin.Infrastructure;
using Web.Areas.Admin.Models.Users;
using Web.Infrastructure;
using Web.Infrastructure.Models;
using Web.Infrastructure.Security;

namespace Web.Areas.Admin.Controllers
{
    /// <summary>
    /// Controller for user management
    /// </summary>
    [AdminAuthorization]
    public partial class UsersController : AdminController
    {
        private readonly IUsersService _usersService;

        /// <summary>
        /// Initializes a new instance of the <see cref="UsersController" /> class.
        /// </summary>
        /// <param name="usersService">The users service.</param>
        public UsersController(IUsersService usersService)
        {
            _usersService = usersService;
        }

        /// <summary>
        /// Return empty view for synchronize with client routes
        /// </summary>
        public virtual ActionResult Index()
        {
            return View(MVC.Admin.Shared.Views.Empty);
        }

        /// <summary>
        /// Listings the template.
        /// </summary>
        public virtual ActionResult ListingTemplate()
        {
            return BackBoneView(MVC.Admin.Users.Views.Listing);
        }

        /// <summary>
        /// Listings the specified sort.
        /// </summary>
        /// <param name="sort">The sort.</param>
        /// <param name="size">The size.</param>
        /// <param name="page">The page.</param>
        /// <param name="filter">The filter.</param>
        [ListingAction("Email")]
        public virtual ActionResult Listing(GridSortOptions sort, int size, int page, UserFilter filter)
        {
            var model = _usersService.GetUserListing(
                page, size, sort.Column, sort.Direction != SortDirection.Descending ? 0 : 1, filter);
            return BackBoneJson(model);
        }

        /// <summary>
        /// Deletes selected items.
        /// </summary>
        /// <param name="items">Items to delete.</param>
        public virtual ActionResult Delete(int[] items)
        {
            var model = new BaseModel();
            foreach (var item in items)
            {
                try
                {
                    _usersService.Delete(item);
                }
                catch (ServiceException exception)
                {
                    ModelState.AddModelError(string.Empty, "Could not delete user with id: " + item);
                    Trace.TraceError(exception.ToString());
                }
            }
            model.Errors = GetErrors;
            if (ModelState.IsValid)
            {
                model.SuccessMessage = "Users have been successfully deleted.";
            }
            return Json(model);
        }

        /// <summary>
        /// Return empty view for synchronize with client routes
        /// </summary>
        [HttpGet]
        public virtual ActionResult Create()
        {
            return View(MVC.Admin.Shared.Views.Empty);
        }

        /// <summary>
        /// Creates the template.
        /// </summary>
        public virtual ActionResult CreateTemplate()
        {
            return BackBoneView(MVC.Admin.Users.Views.Create, new UserCreateModel());
        }

        /// <summary>
        /// Creates the specified model.
        /// </summary>
        /// <param name="model">The model.</param>[HttpPost]
        public virtual ActionResult Create(UserCreateModel model)
        {
            if (!ModelState.IsValid)
            {
                model.Errors = GetErrors;
                return Json(model);
            }
            var user = (User)model;
            try
            {
                _usersService.Create(user);
                model.SuccessMessage = "User has been successfully created.";
                return Json(model);
            }
            catch (ServiceException exception)
            {
                ModelState.AddModelError(string.Empty, exception.Message);
                model.Errors = GetErrors;
                return Json(model);
            }
        }

        /// <summary>
        /// Show form for editing the specified user.
        /// </summary>
        /// <param name="userId">The user id.</param>
        [HttpGet]
        public virtual ActionResult Edit(int? userId)
        {
            var model = new UserEditModel();
            if (!userId.HasValue)
            {
                model.Errors = new List<ErrorModel>
                    {
                        new ErrorModel("Empty value")
                    };
                return BackBoneJson(model);
            }
            var user = _usersService.GetUserById(userId.Value);

            if (null == user)
            {
                model.Errors = new List<ErrorModel>
                    {
                        new ErrorModel(string.Format("User {0} was not found.", userId))
                    };
                return BackBoneJson(new UserEditModel());
            }

            model = new UserEditModel(user);

            return BackBoneJson(model);
        }

        /// <summary>
        /// Edits template.
        /// </summary>
        [HttpGet]
        public virtual ActionResult EditTemplate()
        {
            return BackBoneView(MVC.Admin.Users.Views.Edit, new UserEditModel());
        }

        /// <summary>
        /// Save the specified user.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <param name="model">The model.</param>
        [HttpPost]
        public virtual ActionResult Edit(int userId, UserEditModel model)
        {
            if (!ModelState.IsValid)
            {
                model.Errors = GetErrors;
                return Json(model);
            }
            var user = _usersService.GetUserById(userId);
            user += model;
            try
            {
                _usersService.Save(user);

                model.SuccessMessage = "User has been successfully updated.";

                return Json(model);
            }
            catch (ServiceException exception)
            {
                ModelState.AddModelError(string.Empty, exception.Message);
                model.Errors = GetErrors;
                return Json(model);
            }
        }

        public virtual ActionResult Validate(int? userId, string email, string login)
        {
            var idParam = userId.HasValue ? userId.Value : 0;
            var result = _usersService.ValidateUser(idParam, email, login);
            return Json(result);
        }
    }
}